/*
 * @Author: 0x9DEFA478
 * @Date: 2021-11-06 22:03:00
 * @LastEditTime: 2023-03-19 21:27:06
 * @LastEditors: 0x9DEFA478
 * @Description: 
 *    多重队列实现
 *       无发送对象限制(是否中断 数量等)
 *    对于接收,只有线程能接收多重队列
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "./H_ThreadScheduler_Core.h"
#include "../LL/H_ThreadScheduler_LL.h"




extern H_TS* H_TS_Core;




//数据写入
static int SubQueue_Write(H_TS_MultipleQueue* MultipleQueue,Hsize Index,const void* Data){
  struct _H_TS_MultipleQueue_SubQueue* SubQueue;
  Hsize I;
  Hsize O;
  Hsize Empty;
  volatile Hbyte* Messages;
  const Hbyte* src;
  Hsize i;

  SubQueue=&((struct _H_TS_MultipleQueue_SubQueue*)MultipleQueue->Queues)[Index];

  I=SubQueue->I;
  O=SubQueue->O;

  if(I<O){
    Empty=O-I;
  }else{
    Empty=MultipleQueue->NumOfMessages-I+O;
  }

  if(Empty<=1){
    return -1;
  }

  src=Data;
  i=MultipleQueue->MessageSize;
  Messages=&SubQueue->Messages[I*i];
  while(i>7){
    i-=8;
    
    Messages[0]=src[0];
    Messages[1]=src[1];
    Messages[2]=src[2];
    Messages[3]=src[3];
    Messages[4]=src[4];
    Messages[5]=src[5];
    Messages[6]=src[6];
    Messages[7]=src[7];

    src=&src[8];
    Messages=&Messages[8];
  }
  while(i>1){
    i-=2;
    
    Messages[0]=src[0];
    Messages[1]=src[1];

    src=&src[2];
    Messages=&Messages[2];
  }
  if(i>0){
    i--;
    
    Messages[0]=src[0];

    src=&src[1];
    Messages=&Messages[1];
  }

  if(I==(MultipleQueue->NumOfMessages-1)){
    SubQueue->I=0;
  }else{
    SubQueue->I=I+1;
  }

  return 0;
}

//读取数据
static int SubQueue_Read(H_TS_MultipleQueue* MultipleQueue,Hsize Index,void* Data){
  struct _H_TS_MultipleQueue_SubQueue* SubQueue;
  Hsize I;
  Hsize O;
  volatile Hbyte* Messages;
  Hbyte* dst;
  Hsize i;

  SubQueue=&((struct _H_TS_MultipleQueue_SubQueue*)MultipleQueue->Queues)[Index];

  I=SubQueue->I;
  O=SubQueue->O;

  if(I!=O){
    //有信号量

    dst=Data;
    i=MultipleQueue->MessageSize;
    Messages=&SubQueue->Messages[O*i];
    while(i>7){
      i-=8;
      
      dst[0]=Messages[0];
      dst[1]=Messages[1];
      dst[2]=Messages[2];
      dst[3]=Messages[3];
      dst[4]=Messages[4];
      dst[5]=Messages[5];
      dst[6]=Messages[6];
      dst[7]=Messages[7];

      dst=&dst[8];
      Messages=&Messages[8];
    }
    while(i>1){
      i-=2;
      
      dst[0]=Messages[0];
      dst[1]=Messages[1];

      dst=&dst[2];
      Messages=&Messages[2];
    }
    if(i>0){
      i--;
      
      dst[0]=Messages[0];

      dst=&dst[1];
      Messages=&Messages[1];
    }

    if(O==(MultipleQueue->NumOfMessages-1)){
      SubQueue->O=0;
    }else{
      SubQueue->O=O+1;
    }
    return 0;
  }

  return -1;
}

//让等待的线程的状态变成就绪
static void MultipleQueue_RequestReady_ISR(H_TS_MultipleQueue* MultipleQueue){
  H_TS_Thread* Owner;
  Hsize InIsThread1;
  Hsize OutIsThread1;

  int retVal;

  Owner=MultipleQueue->Owner;
  if(Owner!=NULL){
    //有线程正在等待邮箱

    switch(Owner->Status){
      case vH_TS_Thread_Status_Block:

        Owner->Status=vH_TS_Thread_Status_Ready;//线程就绪
        MultipleQueue->Owner=NULL;//清除占用标记

        //让调度中断处理链表


        //尝试添加到快速通道
        H_TS_ThreadAddToUnblockThread(Owner,H_TS_Core->UnblockThread,InIsThread1,OutIsThread1,retVal);

        if(retVal!=0){
#if vH_TS_BlockThreadListNum > 1
          H_TS_Core->BlockThreadsEvents[Owner->List.Block.ListId]=-1;
#endif
          H_TS_Core->BlockThreadsEvent=-1;
        }

        oH_TS_ISR_CallScheduleISR();

        break;
      case vH_TS_Thread_Status_TimeBlock:

        Owner->Status=vH_TS_Thread_Status_Ready;//线程就绪
        MultipleQueue->Owner=NULL;//清除占用标记

        //让调度中断处理链表
        

        //尝试添加到快速通道
        H_TS_ThreadAddToUnblockThread(Owner,H_TS_Core->TimeUnblockThread,InIsThread1,OutIsThread1,retVal);
        
        if(retVal!=0){
          H_TS_Core->TimeBlockThreadsEvent=-1;
        }

        oH_TS_ISR_CallScheduleISR();

        break;
      case vH_TS_Thread_Status_Ready:
        //这是重入导致的 虽然会导致一些重复操作 但不影响结果
        //直接返回即可
        break;

      default:
        oH_TS_Crash("H_TS:MultipleQueue_RequestReady_ISR()出现严重错误\r\n");
        for(;;){
          //H_TS出BUG了!!
        }
    }
  }
}

//让等待的线程的状态变成就绪
static void MultipleQueue_RequestReady(H_TS_MultipleQueue* MultipleQueue){
  H_TS_Thread* Owner;
  Hsize InIsThread1;
  Hsize OutIsThread1;

  int retVal;

  Owner=MultipleQueue->Owner;
  if(Owner!=NULL){
    //有线程正在等待邮箱

    switch(Owner->Status){
      case vH_TS_Thread_Status_Block:

        Owner->Status=vH_TS_Thread_Status_Ready;//线程就绪
        MultipleQueue->Owner=NULL;//清除占用标记

        //让调度中断处理链表


        //尝试添加到快速通道
        H_TS_ThreadAddToUnblockThread(Owner,H_TS_Core->UnblockThread,InIsThread1,OutIsThread1,retVal);

        if(retVal!=0){
#if vH_TS_BlockThreadListNum > 1
          H_TS_Core->BlockThreadsEvents[Owner->List.Block.ListId]=-1;
#endif
          H_TS_Core->BlockThreadsEvent=-1;
        }

        oH_TS_ResumeSchedulerFixed();

        break;
      case vH_TS_Thread_Status_TimeBlock:

        Owner->Status=vH_TS_Thread_Status_Ready;//线程就绪
        MultipleQueue->Owner=NULL;//清除占用标记

        //让调度中断处理链表
        

        //尝试添加到快速通道
        H_TS_ThreadAddToUnblockThread(Owner,H_TS_Core->TimeUnblockThread,InIsThread1,OutIsThread1,retVal);
        
        if(retVal!=0){
          H_TS_Core->TimeBlockThreadsEvent=-1;
        }

        oH_TS_ResumeSchedulerFixed();

        break;
      case vH_TS_Thread_Status_Ready:
        //这是被中断抢占导致的 虽然会导致一些重复操作 但不影响结果
        
        oH_TS_ResumeSchedulerAuto();
        break;

      default:
        oH_TS_Crash("H_TS:MultipleQueue_RequestReady()出现严重错误\r\n");
        for(;;){
          //H_TS出BUG了!!
        }
    }
  }
}




/**
 * @brief 向队列发送数据 中断调用
 * @param MultipleQueue 要操作的队列
 * @param Data 指向要发送的数据
 * @return 0:成功 -1:队列已满或中断嵌套过多
 */
int H_TS_MultipleQueueSend_ISR(H_TS_MultipleQueue* MultipleQueue,const void* Data){
  int Result;
  Hsize Index;
  Hsize NextIndex;
  Hsize AddCnt;
  Hsize NumOfQueues;

  Result=-1;
  AddCnt=0;
  NumOfQueues=MultipleQueue->NumOfQueues;

  Index=MultipleQueue->ReEnter;//ReEnter每次调用后都会复原, 无需线程(中断)保护. 因为即使被抢占了, 抢占的线程(中断)在退出之前会将ReEnter复原
  if(Index<NumOfQueues){
    do{

      NextIndex=Index+1;
      MultipleQueue->ReEnter=NextIndex;//标记占用
      AddCnt++;

      //尝试发送消息
      if(0==SubQueue_Write(MultipleQueue,Index,Data)){
        Result=0;
      }

      Index=NextIndex;

    }while((Result!=0)&&(Index<NumOfQueues));//如果消息发送成功或者所有消息满退出循环

    NextIndex-=AddCnt;
    MultipleQueue->ReEnter=NextIndex;

    if(Result==0){
      //写入成功
      MultipleQueue->AddFlag=0;
      MultipleQueue_RequestReady_ISR(MultipleQueue);
    }
  }
  
  return Result;
}

/**
 * @brief 向队列发送数据
 * @param MultipleQueue 要操作的队列
 * @param Data 指向要发送的数据
 * @return 0:成功 -1:邮箱已满
 */
int H_TS_MultipleQueueSend(H_TS_MultipleQueue* MultipleQueue,const void* Data){
  int Result;
  Hsize Index;

  Result=-1;

  oH_TS_SchedulerSuspend();

  Index=MultipleQueue->ReEnter;//ReEnter每次调用后都会复原, 无需线程(中断)保护. 因为即使被抢占了, 抢占的线程(中断)在退出之前会将ReEnter复原

  oH_TS_DebugAssert(Index!=0,"线程访问有限是互斥的(由禁止调度保证), 不可能出现这种情况");

  MultipleQueue->ReEnter=1;//标记占用

  //尝试发送消息
  if(0==SubQueue_Write(MultipleQueue,Index,Data)){
    Result=0;
  }
  
  MultipleQueue->ReEnter=0;
  
  if(Result==0){
    //写入成功
    MultipleQueue->AddFlag=0;
    MultipleQueue_RequestReady(MultipleQueue);
  }else{
    oH_TS_ResumeSchedulerAuto();
  }
  
  return Result;
}

/**
 * @brief 从队列中接收数据
 * @param MultipleQueue 要操作的队列
 * @param Data 指向容纳数据的内存
 * @return 无
 */
void H_TS_MultipleQueueReceive(H_TS_MultipleQueue* MultipleQueue,void* Data){
  H_TS_Thread* _this;
  H_TS_Thread* p_next;
  H_TS_Thread* p_last;
#if vH_TS_BlockThreadListNum > 1
  Hsize ListId;
#endif
  Hsize InIsThread1;
  Hsize OutIsThread1;

  int retVal;
  
  _this=cH_TS_ThisThread(H_TS_Core);

  MultipleQueue->AddFlag=-1;

  if(0==H_TS_MultipleQueueTryReceive(MultipleQueue,Data)){
    return;
  }

  //无信号量 开始阻塞

  oH_TS_SchedulerSuspend();

  _this->Status=vH_TS_Thread_Status_Block;
  _this->BlockObject.Block.BlockObject=(void*)&MultipleQueue->Owner;

  //从就绪链表里移除
  H_TS_ThreadRemoteThisFromReadyList(_this,p_next,p_last);

  //添加到阻塞链表
#if vH_TS_BlockThreadListNum > 1
  H_TS_ThreadAddToBlockList(_this,p_next,ListId);
#else
  H_TS_ThreadAddToBlockList(_this,p_next);
#endif

  //标记信号量拥有线程
  MultipleQueue->Owner=_this;

  if(MultipleQueue->AddFlag==0){
    if(MultipleQueue->Owner!=NULL){
      //在修改链表期间有信号量释放 中断不会触发调度中断
      
      _this->Status=vH_TS_Thread_Status_Ready;//线程就绪
      MultipleQueue->Owner=NULL;//清除占用标记

      //让调度中断处理链表


      //尝试添加到快速通道
      H_TS_ThreadAddToUnblockThread(_this,H_TS_Core->UnblockThread,InIsThread1,OutIsThread1,retVal);

      if(retVal!=0){
#if vH_TS_BlockThreadListNum > 1
        H_TS_Core->BlockThreadsEvents[_this->List.Block.ListId]=-1;
#endif
        H_TS_Core->BlockThreadsEvent=-1;
      }

    }
  }

  oH_TS_ResumeScheduler();//允许线程调度

  if(0!=H_TS_MultipleQueueTryReceive(MultipleQueue,Data)){
    //H_TS出现BUG了 这是不应该出现的情况
    oH_TS_Crash("H_TS:H_TS_MultipleQueueReceive()出现严重错误\r\n");
    for(;;){}
  }
  
}

/**
 * @brief 尝试从队列中接收数据
 * @param MultipleQueue 要操作的队列
 * @param Data 指向容纳数据的内存
 * @return 0:成功 其他:获取失败
 */
int H_TS_MultipleQueueTryReceive(H_TS_MultipleQueue* MultipleQueue,void* Data){
  Hsize NumOfQueues;
  Hsize i;

  NumOfQueues=MultipleQueue->NumOfQueues;
  for(i=0;i<NumOfQueues;i++){
    if(0==SubQueue_Read(MultipleQueue,i,Data)){
      return 0;
    }
  }

  return -1;
}

/**
 * @brief 从队列中接收数据 时间限制
 * @param MultipleQueue 要操作的队列
 * @param Data 指向容纳数据的内存
 * @param Timeout 最大等待时间
 * @return 0:成功 其他:获取失败
 */
int H_TS_MultipleQueueReceive_Time(H_TS_MultipleQueue* MultipleQueue,void* Data,H_TS_Tick Timeout){
  H_TS_Thread* _this;
  H_TS_Thread* p_next;
  H_TS_Thread* p_last;
  Hsize InIsThread1;
  Hsize OutIsThread1;

  int retVal;

  _this=cH_TS_ThisThread(H_TS_Core);

  MultipleQueue->AddFlag=-1;

  if(0==H_TS_MultipleQueueTryReceive(MultipleQueue,Data)){
    return 0;
  }

  if(Timeout<1){
    return -1;
  }

  //无信号量 开始阻塞

  oH_TS_SchedulerSuspend();

  _this->Status=vH_TS_Thread_Status_TimeBlock;
  _this->BlockObject.TimeBlock.BlockObject=(void*)&MultipleQueue->Owner;

  //从就绪链表里移除
  H_TS_ThreadRemoteThisFromReadyList(_this,p_next,p_last);

  //添加到时间限制阻塞链表
  H_TS_ThreadAddToTimeBlockList(_this,Timeout);

  //标记消息队列拥有线程
  MultipleQueue->Owner=_this;

  if(MultipleQueue->AddFlag==0){
    if(MultipleQueue->Owner!=NULL){
      //在修改链表期间有信号量释放 中断不会触发调度中断
      
      _this->Status=vH_TS_Thread_Status_Ready;//线程就绪
      MultipleQueue->Owner=NULL;//清除占用标记

      //让调度中断处理链表
      
      
      //尝试添加到快速通道
      H_TS_ThreadAddToUnblockThread(_this,H_TS_Core->TimeUnblockThread,InIsThread1,OutIsThread1,retVal);
        
      if(retVal!=0){
        H_TS_Core->TimeBlockThreadsEvent=-1;
      }
      
    }
  }

  oH_TS_ResumeScheduler();//允许线程调度

  if(0!=H_TS_MultipleQueueTryReceive(MultipleQueue,Data)){
    //超时
    return -1;
  }

  return 0;
}



